﻿using Base.Api.Models;
using Base.Api.Repository;
using Base.Data.Entity;
using Base.Data.Entity.Base;
using Common.AspNetCore;
using Common.Infrastructure;
using Common.Infrastructure.Utils;
using Common.RunModels.Base;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace Base.Api.Service
{
    public class HRSyncService : CommonService
    {
        private readonly BaseRepository baseRepository;

        public HRSyncService(IServiceProvider provider, BaseRepository baseRep) : base(provider)
        {
            this.baseRepository = baseRep;
        }

        public async Task<HRSyncByDepartResultModel> SyncDepartAsync(HRSyncByDepartParamModel model)
        {
            var organization = await this.baseRepository.CommonRepository.GetEntityAsync<t_organization>(model.OrgId);
            if (organization == null || string.IsNullOrWhiteSpace(organization.alias_code))
            {
                return new HRSyncByDepartResultModel();
            }

            var aliasModels = GetHRSyncOrgAliasCodeModel(organization.alias_code);
            if (!aliasModels.Any())
            {
                return new HRSyncByDepartResultModel();
            }

            var r = await WebApiUtils.PostAsync<UpExtResposeResult<List<UpExtDepartModel>>>(
                $"{model.Url}/api/HR/GetDepartmentByLMesDto",
                new
                {
                    DeptCode = string.Join(",", aliasModels.Select(t => t.AliasCode)),
                });

            HRSyncByDepartResultModel resultModel = new HRSyncByDepartResultModel();

            if (r.data == null || !r.is_success)
            {
                if (!r.is_success)
                {
                    resultModel.Message = "Error:" + r.error_message;
                }

                return resultModel;
            }

            resultModel.Count = r.data.Count;

            var topdepartcodes = aliasModels.Select(t => t.AliasCode).ToList();

            r.data.ForEach(t =>
            {
                if (topdepartcodes.Any(t1 => t1 == t.dept_id))
                {
                    t.parent_id = null;
                }
            });

            var departCodes = r.data.Select(t => t.dept_id).ToList();
            departCodes.AddRange(r.data.Where(t => !string.IsNullOrWhiteSpace(t.parent_id)).Select(t => t.parent_id));
            departCodes = departCodes.Distinct().ToList();
            var departments = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_department>(null, t => departCodes.Contains(t.code));

            List<t_department> addDepartments = new List<t_department>();
            List<t_department> updateDepartments = new List<t_department>();

            DoSyncDepart(resultModel, model.ApiKey, model.OrgId, r.data, null, null, departments, addDepartments, updateDepartments, aliasModels, null);

            await this.baseRepository.CommitChangesByCommonAsync(() =>
            {
                this.baseRepository.CommonRepository.AddEntities(addDepartments);
                this.baseRepository.CommonRepository.UpdateEntities(updateDepartments);
            });

            return resultModel;
        }

        public async Task<HRSyncByUserResultModel> SyncUsersAsync(HRSyncByUserParamModel model)
        {
            var organization = await this.baseRepository.CommonRepository.GetEntityAsync<t_organization>(model.OrgId);
            if (organization == null || string.IsNullOrWhiteSpace(organization.alias_code))
            {
                return new HRSyncByUserResultModel();
            }

            var aliasModels = GetHRSyncOrgAliasCodeModel(organization.alias_code);
            if (!aliasModels.Any())
            {
                return new HRSyncByUserResultModel();
            }

            var departs = await WebApiUtils.PostAsync<UpExtResposeResult<List<UpExtDepartModel>>>(
              $"{model.Url}/api/HR/GetDepartmentByLMesDto",
              new
              {
                  DeptCode = string.Join(",", aliasModels.Select(t => t.AliasCode)),
              });

            HRSyncByUserResultModel resultModel = new HRSyncByUserResultModel();

            if (departs.data == null || !departs.is_success)
            {
                if (!departs.is_success)
                {
                    resultModel.Message = "Error:" + departs.error_message;
                }

                return resultModel;
            }

            var topdepartcodes = aliasModels.Select(t => t.AliasCode).ToList();
            departs.data.ForEach(t =>
            {
                if (topdepartcodes.Any(t1 => t1 == t.dept_id))
                {
                    t.parent_id = null;
                }
            });

            List<UpExtDepartModel> departModel = new List<UpExtDepartModel>();
            DoDepart(departModel, departs.data, null, aliasModels, null);

            var r = await WebApiUtils.PostAsync<UpExtResposeResult<List<UpExtUserModel>>>(
                $"{model.Url}/api/HR/GetPersonByLMesDto",
                new
                {
                    DeptCode = organization.alias_code,
                });

            if (r.data == null || !r.is_success)
            {
                if (!r.is_success)
                {
                    resultModel.Message = "Error:" + r.error_message;
                }

                return resultModel;
            }

            resultModel.Count = r.data.Count;

            var defaultRoleCodes = model.DefaultRoleCodes?.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            if (defaultRoleCodes == null)
            {
                defaultRoleCodes = new List<string>();
            }

            defaultRoleCodes.Add("WipDefault");
            defaultRoleCodes.Add("WipClientDefault");
            defaultRoleCodes.Add("WipAppDefault");
            defaultRoleCodes.Add("WipWinformDefault");

            List<t_role> addRoles = new List<t_role>();
            var roles = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_role>(null, t => t.org_id == model.OrgId && defaultRoleCodes.Contains(t.code));
            defaultRoleCodes.Where(t => !roles.Any(t1 => t1.code == t)).ForEach(t =>
            {
                var add = new t_role()
                {
                    code = t,
                    name = t,
                    org_id = model.OrgId,
                };
                this.SetEntityId(add);
                if (t.Contains("Client", StringComparison.OrdinalIgnoreCase))
                {
                    add.platform_type = 1;
                }

                if (t.Contains("App", StringComparison.OrdinalIgnoreCase))
                {
                    add.platform_type = 2;
                }

                addRoles.Add(add);
                roles.Add(add);
            });

            await this.baseRepository.CommitChangesByCommonAsync(() =>
            {
                this.baseRepository.CommonRepository.AddEntities(addRoles);
            });

            if (r.data.Count <= 2000)
            {
                await DoSyncUsersSync(resultModel, r.data, model.OrgId, model.ApiKey, roles, departModel);
            }
            else
            {
                List<UpExtUserModel> temp = new List<UpExtUserModel>();
                foreach (var d in r.data)
                {
                    temp.Add(d);
                    if (temp.Count >= 2000)
                    {
                        await DoSyncUsersSync(resultModel, temp, model.OrgId, model.ApiKey, roles, departModel);
                        temp.Clear();
                    }
                }

                await DoSyncUsersSync(resultModel, temp, model.OrgId, model.ApiKey, roles, departModel);
            }

            if (model.IsCheckLeaveUser)
            {
                ////设置为离职状态
                var users = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user>(null, t => t.org_id == model.OrgId);

                List<t_user> updateUsers = new List<t_user>();
                Regex valueRegex = new Regex("^[0-9]*$");

                foreach (var user in users)
                {
                    var code = user.code?.Trim();
                    if (string.IsNullOrWhiteSpace(code) || r.data == null || !r.data.Any() || r.data.Any(t3 => t3.emp_id == code))
                    {
                        continue;
                    }

                    ////用户编号非字符串的跳过
                    if (!valueRegex.IsMatch(code))
                    {
                        continue;
                    }

                    if (code.Contains("Admin", StringComparison.OrdinalIgnoreCase) || code.Contains("System", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    if (user.enable_status == 1)
                    {
                        continue;
                    }

                    user.enable_status = 1;

                    updateUsers.Add(user);
                }

                if (updateUsers.Any())
                {
                    await this.baseRepository.CommitChangesByCommonAsync(() =>
                    {
                        this.baseRepository.CommonRepository.UpdateEntities(updateUsers);
                    });
                }
            }

            return resultModel;
        }

        public async Task<HRSyncByDepartAttendResultModel> GetDepartAttendUserAsync(HRSyncByDepartAttendParamModel model)
        {
            if (model == null || string.IsNullOrWhiteSpace(model.Url) || model.DepartCodes == null || !model.DepartCodes.Any())
            {
                return new HRSyncByDepartAttendResultModel();
            }

            HRSyncByDepartAttendResultModel resultModel = new HRSyncByDepartAttendResultModel();
            var departs = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_department>(null, t => model.DepartCodes.Contains(t.code));
            var departIds = departs.Select(t => t.id).ToList();
            var users = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user>(null, t => departIds.Contains(t.depart_id) && t.enable_status == 0);

            foreach (var depart in departs)
            {
                var tempusers = users.Where(t => t.depart_id == depart.id).ToList();
                var r = await WebApiUtils.PostAsync<UpExtResposeResult<List<UpExtUserAttendModel>>>(
                     $"{model.Url}/api/HR/GetPersonByLMesByDailyAttendDto",
                     new
                     {
                         userCode = string.Join(",", tempusers.Select(t => t.code)),
                         startTime = DateTime.Now.Date,
                     });

                var detail = new HRSyncByDepartAttendDetailResultModel()
                {
                    DepartCode = depart.code,
                    PlanAttendUserQty = tempusers.Count,
                };

                tempusers.ForEach(t =>
                {
                    if (r.data != null && r.data.Any(t1 => t1.employee_id == t.code && t1.punch_time.Value.Date == DateTime.Now.Date))
                    {
                        detail.AuttendUserQty++;
                    }
                    else
                    {
                        detail.UnAttendUserCodes.Add(t.code);
                    }
                });

                resultModel.Details.Add(detail);
            }

            return resultModel;
        }

        /// <summary>
        /// 同步人员证书
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<HRSyncUserCerResultModel> SyncUserCerAsync(HRSyncUserCerParamModel model)
        {
            UpExtUserCerParamModel userCerParamModel = new UpExtUserCerParamModel();

            if (!string.IsNullOrWhiteSpace(model.UserCode))
            {
                userCerParamModel.UserCode = model.UserCode;
            }
            else
            {
                userCerParamModel.StartTime = model.StartTime;
                userCerParamModel.EndTime = model.EndTime;
            }

            var r = await WebApiUtils.PostAsync<UpExtResposeResult<List<UpExtUserCerModel>>>(
                $"{model.Url}/api/HR/GetEmployeeCertificateByLMesDto",
                userCerParamModel);

            HRSyncUserCerResultModel resultModel = new HRSyncUserCerResultModel();

            if (r.data == null || !r.is_success)
            {
                if (!r.is_success)
                {
                    resultModel.Message = "Error:" + r.error_message;
                }

                return resultModel;
            }

            resultModel.Count = r.data.Count;
            var userCodes = r.data.Select(t => t.emp_id);
            var users = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user>(new ApiParam(model.OrgId), t => userCodes.Contains(t.code));

            if (users.Any())
            {
                var userIds = users.Select(t => t.id).ToList();
                var userCertificates = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user_certificate>(new ApiParam(model.OrgId), t => userIds.Contains(t.user_id));
                List<t_user_certificate> addDepartments = new List<t_user_certificate>();
                List<t_user_certificate> updateDepartments = new List<t_user_certificate>();
                List<t_certificate_type> addCertificateTypes = new List<t_certificate_type>();

                await DoSyncUserCer(model.OrgId, r.data, users, userCertificates, addDepartments, updateDepartments, addCertificateTypes);

                await this.baseRepository.CommitChangesByCommonAsync(() =>
                {
                    this.baseRepository.CommonRepository.AddEntities(addDepartments);
                    this.baseRepository.CommonRepository.UpdateEntities(updateDepartments);
                    this.baseRepository.CommonRepository.AddEntities(addCertificateTypes);
                });
            }

            return resultModel;
        }

        private void DoSyncDepart(HRSyncByDepartResultModel result, string apiKey, string orgId, List<UpExtDepartModel> departModels, string parentcode, string parentId, List<t_department> departments, List<t_department> addDepartments, List<t_department> updateDepartments, List<HRSyncOrgAliasCodeModel> aliasModels, HRSyncOrgAliasCodeModel parentAliasModel)
        {
            var tempupex = departModels.Where(t => t.parent_id == parentcode).ToList();

            foreach (var item in tempupex)
            {
                if (string.IsNullOrEmpty(item.parent_id))
                {
                    parentAliasModel = aliasModels?.FirstOrDefault(t => t.AliasCode == item.dept_id);
                }
                else if (parentAliasModel != null && parentAliasModel.IgnoreCodes.Contains(item.dept_id))
                {
                    continue;
                }

                var isadd = false;
                var depart = departments.FirstOrDefault(t => t.code == item.dept_id);
                if (depart == null)
                {
                    depart = new t_department()
                    {
                        org_id = orgId,
                        code = item.dept_id,
                        api_key = apiKey
                    };
                    this.SetEntityId(depart);
                    isadd = true;
                    addDepartments.Add(depart);
                }

                var isline = item.line_dept == "1";

                var isupdate = depart.name != item.cn_name ||
                    depart.parent_id != parentId ||
                    depart.is_line != isline;

                if (!isadd && depart.org_id != orgId)
                {
                    depart.org_id = orgId;
                    isupdate = true;
                }

                if (!isadd && depart.api_key != apiKey)
                {
                    depart.api_key = apiKey;
                    isupdate = true;
                }

                depart.name = item.cn_name;
                depart.parent_id = parentId;
                depart.is_line = isline;

                if (!isadd && isupdate)
                {
                    updateDepartments.Add(depart);
                }

                if (isline)
                {
                    result.Details.Add(new HRSyncByDepartDetailResultModel()
                    {
                        Code = depart.code,
                        Id = depart.id,
                        Name = depart.name,
                        ParentCode = item.parent_id,
                        ParentId = depart.parent_id,
                    });
                }

                DoSyncDepart(result, apiKey, orgId, departModels, item.dept_id, depart.id, departments, addDepartments, updateDepartments, aliasModels, parentAliasModel);
            }
        }

        private void DoDepart(List<UpExtDepartModel> result, List<UpExtDepartModel> departModels, string parentcode, List<HRSyncOrgAliasCodeModel> aliasModels, HRSyncOrgAliasCodeModel parentAliasModel)
        {
            var tempupex = departModels.Where(t => t.parent_id == parentcode).ToList();

            foreach (var item in tempupex)
            {
                if (string.IsNullOrEmpty(item.parent_id))
                {
                    parentAliasModel = aliasModels?.FirstOrDefault(t => t.AliasCode == item.dept_id);
                }
                else if (parentAliasModel != null && parentAliasModel.IgnoreCodes.Contains(item.dept_id))
                {
                    var departs = departModels.Where(t => t.parent_id == item.dept_id);

                    if (departs.Any())
                    {
                        parentAliasModel.IgnoreCodes.AddRange(departs.Select(t => t.dept_id));
                    }

                    result.Add(item);
                }

                DoDepart(result, departModels, item.dept_id, aliasModels, parentAliasModel);
            }
        }

        private async Task DoSyncUsersSync(HRSyncByUserResultModel resultModel, List<UpExtUserModel> list, string orgId, string apiKey, List<t_role> roleLists, List<UpExtDepartModel> departModel)
        {
            if (list == null || !list.Any())
            {
                return;
            }

            if (list.GroupBy(t => t.emp_id).Any(t => t.Count() > 1))
            {
                throw new Exception("emp_id copy");
            }

            HRUserAccessModel accessModel = new HRUserAccessModel();
            List<t_department> departments = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_department>(null, t => t.org_id == orgId);
            var userCodeLists = list.Select(t => t.emp_id).ToList();

            var users = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user>(null, t => userCodeLists.Contains(t.code));
            var userIds = users.Select(t => t.id).ToList();
            var members = userIds.Any() ? await this.baseRepository.CommonRepository.GetEntitiesAsync<t_member>(null, t => userIds.Contains(t.user_id)) : new List<t_member>();
            var memberIds = members.Select(t => t.id).ToList();
            var memberAuthRoles = memberIds.Any() ? await this.baseRepository.CommonRepository.GetEntitiesAsync<t_member_auth_role>(null, t => memberIds.Contains(t.member_id)) : new List<t_member_auth_role>();

            var postcodes = list.Where(t => !string.IsNullOrWhiteSpace(t.job_id)).Select(t => t.job_id).Distinct().ToList();
            var userPosts = postcodes.Any() ? await this.baseRepository.CommonRepository.GetEntitiesAsync<t_user_post>(null, t => postcodes.Contains(t.code)) : new List<t_user_post>();

            postcodes.Where(t => !userPosts.Any(t1 => t1.code == t)).ForEach(t =>
            {
                var sts = list.FirstOrDefault(t1 => t1.job_id == t);

                var add = new t_user_post()
                {
                    code = t,
                    name = sts?.job_name ?? t,
                    org_id = orgId,
                };

                this.SetEntityId(add);
                accessModel.AddUserPosts.Add(add);
                userPosts.Add(add);
            });

            var srcType = typeof(UpExtUserModel);
            var destType = typeof(t_user);

            list.ForEach(t =>
            {
                var ignoreDepart = departModel.FirstOrDefault(s => s.dept_id == t.dept_id);

                if (ignoreDepart != null)
                {
                    return;
                }

                var depart = departments.FirstOrDefault(t1 => t1.code == t.dept_id);
                if (depart != null && depart.org_id != orgId)
                {
                    return;
                }

                var isAdd = false;
                var user = users.FirstOrDefault(t1 => t1.code == t.emp_id);
                if (user == null)
                {
                    user = new t_user()
                    {
                        code = t.emp_id,
                    };
                    this.SetEntityId(user);

                    accessModel.AddUsers.Add(user);
                    users.Add(user);
                    isAdd = true;
                }

                bool isUpdate = false;
                var enablestatus = t.emp_status == "1" ? 0 : 1;
                var sex = LibSysUtils.ToInt(t.sex);
                var workterritory = LibSysUtils.ToInt(t.work_territory);
                var dirIndirClass = LibSysUtils.ToInt(t.dir_indir_class);

                var userPost = userPosts.FirstOrDefault(t1 => t1.code == t.job_id);

                if (isAdd || depart == null || user.depart_id != depart.id)
                {
                    isUpdate = true;
                    user.depart_id = depart?.id;
                }

                if (isAdd || userPost == null || user.user_post_id != userPost.id)
                {
                    isUpdate = true;
                    user.user_post_id = userPost?.id;
                }

                if (isAdd || user.enable_status != enablestatus)
                {
                    isUpdate = true;
                    user.enable_status = enablestatus;
                }

                if (isAdd || user.work_territory != workterritory)
                {
                    isUpdate = true;
                    user.work_territory = workterritory;
                }

                if (isAdd || user.dir_indir_class != dirIndirClass)
                {
                    isUpdate = true;
                    user.dir_indir_class = dirIndirClass;
                }

                if (isAdd || user.sex != sex)
                {
                    isUpdate = true;
                    user.sex = sex;
                }

                if (isAdd || user.org_id != orgId)
                {
                    isUpdate = true;
                    user.org_id = orgId;
                }

                if (isAdd || user.api_key != apiKey)
                {
                    isUpdate = true;
                    user.api_key = apiKey;
                }

                CheckAndUpdateProperty(t, user, srcType, destType, "cn_name", "name", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "position_id", "position_code", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "sequ_id", "sequ_code", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "sequ_name", "sequ_name", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "subsq_id", "subsq_code", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "subsq_name", "subsq_name", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "job_class", "job_class", ref isUpdate);
                CheckAndUpdateProperty(t, user, srcType, destType, "entry_date", "entry_date", ref isUpdate);

                var isAddMember = false;
                var isUpdateMember = false;
                var member = members.FirstOrDefault(t1 => t1.user_id == user.id);
                var usermembers = members.Where(p => p.user_id == user.id).ToList();
                var ismanyDepUser = false;
                if (usermembers != null && usermembers.Count() > 1)
                {
                    ismanyDepUser = true;
                }

                if ((isAdd || user.user_lcp_code != t.login_name) && !ismanyDepUser)
                {
                    isUpdate = true;
                    user.user_lcp_code = t.login_name;
                    CheckAndUpdateProperty(t, user, srcType, destType, "login_name", "user_lcp_code", ref isUpdate);
                }

                if (member == null)
                {
                    member = new t_member()
                    {
                        code = t.emp_id,
                        password = "e10adc3949ba59abbe56e057f20f883e",
                    };
                    this.SetEntityId(member);
                    accessModel.AddMembers.Add(member);
                    isAddMember = true;
                }

                if (depart != null && depart.is_line)
                {
                    roleLists.ForEach(t =>
                    {
                        if (memberAuthRoles.Any(t1 => t1.member_id == member.id && t1.role_id == t.id))
                        {
                            return;
                        }

                        var sts = new t_member_auth_role()
                        {
                            member_id = member.id,
                            role_id = t.id,
                            org_id = orgId,
                        };

                        this.SetEntityId(sts);

                        accessModel.AddMemberAuthRoles.Add(sts);
                    });
                }

                if (userPost != null && depart != null && (userPost.name.Contains("线长") || userPost.name.Contains("助线")))
                {
                    var s = resultModel.Details.FirstOrDefault(t1 => t1.DepartId == depart.id);
                    if (s == null)
                    {
                        s = new HRSyncByUserDetailResultModel()
                        {
                            DepartCode = depart.code,
                            DepartId = depart.id,
                        };

                        resultModel.Details.Add(s);
                    }

                    var type = userPost.name == "线长" ? 1 : 2;

                    if (!s.Users.Any(t1 => t1.UserId == user.id))
                    {
                        s.Users.Add(new HRSyncByUserDetailUserResultModel()
                        {
                            UserId = user.id,
                            UserType = type,
                        });
                    }

                    if (type == 1 && string.IsNullOrEmpty(depart.user_id))
                    {
                        depart.user_id = user.id;
                        if (!accessModel.UpdateDepartments.Any(t1 => t1.id == depart.id))
                        {
                            accessModel.UpdateDepartments.Add(depart);
                        }
                    }
                }
                else if (userPost != null && depart != null && (userPost.name.Contains("课长") || userPost.name.Contains("组长") || userPost.name.Contains("经理") || userPost.name.Contains("总监") || userPost.name.Contains("厂长")))
                {
                    if (depart.user_id != user.id)
                    {
                        depart.user_id = user.id;
                        if (!accessModel.UpdateDepartments.Any(t1 => t1.id == depart.id))
                        {
                            accessModel.UpdateDepartments.Add(depart);
                        }
                    }
                }

                if ((isAddMember || depart == null || member.depart_id != depart.id) && !ismanyDepUser)
                {
                    isUpdateMember = true;
                    member.depart_id = depart?.id;
                }

                if (isAddMember || member.user_id != user.id)
                {
                    isUpdateMember = true;
                    member.user_id = user.id;
                }

                if (isAddMember || member.name != t.cn_name)
                {
                    isUpdateMember = true;
                    member.name = t.cn_name;
                }

                if ((isAddMember || member.api_key != apiKey) && !ismanyDepUser)
                {
                    isUpdate = true;
                    member.api_key = apiKey;
                }

                if ((isAddMember || member.org_id != orgId) && !ismanyDepUser)
                {
                    isUpdateMember = true;
                    member.org_id = orgId;
                }

                if (!isAdd && isUpdate && !accessModel.UpdateUsers.Any(t1 => t1.id == user.id))
                {
                    accessModel.UpdateUsers.Add(user);
                }

                if (!isAddMember && isUpdateMember && !accessModel.UpdateMembers.Any(t1 => t1.id == member.id))
                {
                    accessModel.UpdateMembers.Add(member);
                }
            });

            await this.baseRepository.CommitChangesByCommonAsync(() =>
            {
                this.baseRepository.CommonRepository.AddEntities(accessModel.AddUsers);
                this.baseRepository.CommonRepository.AddEntities(accessModel.AddUserPosts);
                this.baseRepository.CommonRepository.AddEntities(accessModel.AddRoles);
                this.baseRepository.CommonRepository.AddEntities(accessModel.AddMembers);
                this.baseRepository.CommonRepository.AddEntities(accessModel.AddMemberAuthRoles);

                this.baseRepository.CommonRepository.UpdateEntities(accessModel.UpdateUsers);
                this.baseRepository.CommonRepository.UpdateEntities(accessModel.UpdateMembers);
                this.baseRepository.CommonRepository.UpdateEntities(accessModel.UpdateDepartments);
            });
        }

        private void CheckAndUpdateProperty(object src, object dest, Type srcType, Type destType, string srcName, string destName, ref bool isUpdate)
        {
            var targetP = destType.GetProperty(destName);
            var srcP = srcType.GetProperty(srcName);
            if (targetP != null && srcP.PropertyType == targetP.PropertyType)
            {
                var valuesrc = srcP.GetValue(src, null);
                var valuedest = targetP.GetValue(dest, null);
                if (valuedest == null || valuedest == null || valuedest.ToString() != valuesrc.ToString())
                {
                    isUpdate = true;
                }

                try
                {
                    targetP.SetValue(dest, valuesrc);
                }
                catch
                {
                }
            }
        }

        private List<HRSyncOrgAliasCodeModel> GetHRSyncOrgAliasCodeModel(string aliasCode)
        {
            if (string.IsNullOrWhiteSpace(aliasCode))
            {
                return new List<HRSyncOrgAliasCodeModel>();
            }

            var ret = new List<HRSyncOrgAliasCodeModel>();

            var ts = aliasCode.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            ts.ForEach(t =>
            {
                if (t.Contains("/"))
                {
                    var ps = t.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                    if (ps.Length >= 2)
                    {
                        ret.Add(new HRSyncOrgAliasCodeModel() { AliasCode = ps[0], IgnoreCodes = ps[1].Split(':').ToList() });
                    }
                }
                else
                {
                    ret.Add(new HRSyncOrgAliasCodeModel() { AliasCode = t });
                }
            });

            return ret;
        }

        private async Task DoSyncUserCer(string orgId, List<UpExtUserCerModel> userCerModels, List<t_user> users, List<t_user_certificate> userCertificates, List<t_user_certificate> addUserCertificates, List<t_user_certificate> updateUserCertificates, List<t_certificate_type> addCertificateTypes)
        {
            var certificateTypeCodes = userCerModels.Select(t => t.type_id);
            var certificateTypes = await this.baseRepository.CommonRepository.GetEntitiesAsync<t_certificate_type>(new ApiParam(orgId), t => certificateTypeCodes.Contains(t.code));

            foreach (var item in userCerModels)
            {
                var user = users.FirstOrDefault(t => t.code == item.emp_id);

                if (user == null)
                {
                    continue;
                }

                var certificateType = certificateTypes.FirstOrDefault(t => t.code == item.type_id);

                if (certificateType == null)
                {
                    certificateType = addCertificateTypes.FirstOrDefault(t => t.code == item.type_id);
                }

                if (certificateType == null)
                {
                    certificateType = new t_certificate_type()
                    {
                        code = item.type_id,
                        name = item.type_name,
                        org_id = orgId
                    };

                    this.SetEntityId(certificateType);
                    addCertificateTypes.Add(certificateType);
                }

                bool isUpdate = false;

                var userCertificate = userCertificates.FirstOrDefault(t => t.user_id == user?.id && t.certificate_id == certificateType.id);

                if (userCertificate == null)
                {
                    userCertificate = new t_user_certificate()
                    {
                        org_id = orgId,
                        user_id = user.id,
                        expire_from = item.expire_from,
                        expire_to = item.expire_to,
                        receive_time = item.receive_time,
                        hold_month = item.hold_month,
                        hr_modify_time = item.modi_time,
                        certificate_id = certificateType.id,
                        code = item.certificate_id,
                        name = item.certificate_name,
                        agency = item.agency
                    };
                    this.SetEntityId(userCertificate);
                    addUserCertificates.Add(userCertificate);
                }
                else
                {
                    isUpdate = false;

                    if (userCertificate.hr_modify_time != item.modi_time)
                    {
                        userCertificate.hr_modify_time = item.modi_time;
                        isUpdate = true;
                    }

                    if (userCertificate.expire_to != item.expire_to)
                    {
                        userCertificate.expire_to = item.expire_to;
                        isUpdate = true;
                    }

                    if (userCertificate.agency != item.agency)
                    {
                        userCertificate.agency = item.agency;
                        isUpdate = true;
                    }

                    if (isUpdate)
                    {
                        updateUserCertificates.Add(userCertificate);
                    }
                }
            }
        }
    }
}
